<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="description" content="有了这个，就不用到处去找重复的了">
  <meta name="keyword" content="hexo, vuejs">
  
    <link rel="shortcut icon" href="/css/images/logo.png">
  
  <title>
    
      （写一个自己的HEXO主题 | 杂记
    
  </title>
  <link href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="//cdn.bootcss.com/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
  <link href="//cdn.bootcss.com/highlight.js/9.12.0/styles/tomorrow.min.css" rel="stylesheet">
  <link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/plugins/gitment.css">
<link rel="stylesheet" href="/css/plugins/search.css">
  <script src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  <script src="//cdn.bootcss.com/geopattern/1.2.3/js/geopattern.min.js"></script>
  <script src="//cdn.bootcss.com/nprogress/0.2.0/nprogress.min.js"></script>
  <script src="/js/qrious.js"></script>
<script src="/js/gitment.js"></script>
<script src="/js/search.js"></script>
</head>
  <body>
    <header class="header fixed-header">
  <div class="header-container">
    <a class="home-link" href="/">
      <div class="logo"></div>
      <span>杂记</span>
    </a>
    <ul class="right-list">
        <li class="list-item">   
          <span class="algolia-autocomplete algolia-autocomplete-right" style="position: relative; display: inline-block; direction: ltr;">
            <input type="text" id="local-search-input" class="search-query st-default-search-input aa-input" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-owns="algolia-autocomplete-listbox-0" dir="auto" style="position: relative; vertical-align: top;">
          </span>
        </li>
      
        <li class="list-item">
          
            <a href="/" class="item-link">Home</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/tags/" class="item-link">Tags</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/archives/" class="item-link">Archives</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/project/" class="item-link">Projects</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/about/" class="item-link">About</a>
          
        </li>
      
    </ul>
    <div class="menu">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <div id="menu-mask" class="menu-mask">
      <ul class="menu-list">
        <li class="menu-item">   
          <span class="algolia-autocomplete algolia-autocomplete-right" style="position: relative; display: inline-block; direction: ltr;">
            <input type="text" id="mobile-search-input" class="search-query st-default-search-input aa-input" autocomplete="off" spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-owns="algolia-autocomplete-listbox-0" dir="auto" style="position: relative; vertical-align: top;">
          </span>
        </li>
        
          <li class="menu-item">
            
              <a href="/" class="menu-link">Home</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/tags/" class="menu-link">Tags</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/archives/" class="menu-link">Archives</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/project/" class="menu-link">Projects</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/about/" class="menu-link">About</a>
            
          </li>
        
      </ul>
    </div>
  </div>
<div class="ins-search">
    <div class="ins-search-mask"></div>
    <div class="ins-search-container">
        <div class="ins-input-wrapper">
            <input type="text" class="ins-search-input" placeholder="输入关键词" />
            <span class="ins-close ins-selectable"><i class="fa fa-times-circle"></i></span>
        </div>
        <div class="ins-section-wrapper">
            <div class="ins-section-container"></div>
        </div>
    </div>
</div>
<script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '博文',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '未定义',
        },
        ROOT_URL: '/',
        CONTENT_URL: '/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/js/insight.js"></script>

<div id="result-wrap" class="ins-search">
    <div id="local-search-result"></div>
</div>

<script type="text/javascript">      
     var search_path = "search.xml";
     if (search_path.length == 0) {
      search_path = "search.xml";
     }
     var path = "/" + search_path;
     searchFunc(path, 'local-search-input', 'local-search-result');
     searchFunc(path, 'mobile-search-input', 'local-search-result');
</script>
</header>

    <div id="article-banner">
  <h2>（写一个自己的HEXO主题</h2>
  <p class="post-date">2017-08-30</p>
  <div class="arrow-down">
    <a href="javascript:;"></a>
  </div>
</div>

    <aside class="post-widget">
        <nav class="post-toc-wrap" id="post-toc">
            <h4>TOC</h4>
            <ol class="post-toc"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#起步"><span class="post-toc-number">1.</span> <span class="post-toc-text">起步</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#布局"><span class="post-toc-number">2.</span> <span class="post-toc-text">布局</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#编写布局文件-layout-ejs"><span class="post-toc-number">2.0.1.</span> <span class="post-toc-text">编写布局文件(layout.ejs)</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#其他模板文件"><span class="post-toc-number">2.0.2.</span> <span class="post-toc-text">其他模板文件</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#index-ejs"><span class="post-toc-number">2.0.3.</span> <span class="post-toc-text">index.ejs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#post-ejs"><span class="post-toc-number">2.0.4.</span> <span class="post-toc-text">post.ejs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#page-ejs"><span class="post-toc-number">2.0.5.</span> <span class="post-toc-text">page.ejs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#partial-article-ejs"><span class="post-toc-number">2.0.6.</span> <span class="post-toc-text">_partial/article.ejs</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#tag-ejs"><span class="post-toc-number">2.0.7.</span> <span class="post-toc-text">tag.ejs</span></a></li></ol></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#变量"><span class="post-toc-number">3.</span> <span class="post-toc-text">变量</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#辅助函数-Helper"><span class="post-toc-number">4.</span> <span class="post-toc-text">辅助函数(Helper)</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#其他的Helper"><span class="post-toc-number">4.0.1.</span> <span class="post-toc-text">其他的Helper:</span></a></li></ol></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#样式"><span class="post-toc-number">5.</span> <span class="post-toc-text">样式</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#其他"><span class="post-toc-number">6.</span> <span class="post-toc-text">其他</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#添加对多说和Disqus的支持"><span class="post-toc-number">6.0.1.</span> <span class="post-toc-text">添加对多说和Disqus的支持</span></a></li><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#使用highlight-js提供代码高亮"><span class="post-toc-number">6.0.2.</span> <span class="post-toc-text">使用highlight.js提供代码高亮</span></a></li></ol></li></ol></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#最后"><span class="post-toc-number">7.</span> <span class="post-toc-text">最后</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-4"><a class="post-toc-link" href="#参考资源"><span class="post-toc-number">7.0.1.</span> <span class="post-toc-text">参考资源</span></a></li></ol></li></ol></li></ol>
        </nav>
    </aside>
    
<main class="app-body">
  <article class="post-article">
    <section class="markdown-content" id="post-content"><p>最开始折腾Hexo的时候感觉这东西很神奇，通过他和github搭配就能生成免费的静态博客，而且还有丰富的主题可以选择，当我刚入Hexo的时候默认主题是<code>landscape</code>，后来又使用过<code>NexT</code>，是一款很漂亮的主题，但是除此之外，还有很多好看的主题，我很好奇这些主题都是怎么写出来的，于是乎就仿照<code>landscape</code>主题开始研究，写自己的主题，也就是<a href="http://www.showonne.com/" target="_blank" rel="external">我自己的博客</a>正在用的主题，项目地址在<a href="https://github.com/showonne/hexo_showonne" target="_blank" rel="external">这里</a>。</p>
<p>完成一个Hexo的主题其实很简单，和写静态页面差不多，只是内容部分通过Hexo的变量去获取，而且Hexo还内置了一些辅助函数帮你快速方便地完成繁琐的处理。</p>
<h2 id="起步"><a href="#起步" class="headerlink" title="起步"></a>起步</h2><p>在写代码之前要先把项目结构搭建好，一个Hexo主题的项目名就是主题名字本身，项目内的目录结构如下: (生成树形图是用的<code>tree</code>， mac上直接<code>brew install tree</code>就可以了，以前不写都不知道囧)</p>
<figure class="highlight mel"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div></pre></td><td class="code"><pre><div class="line">.</div><div class="line">├── _config.yml   <span class="comment">//记录主题配置信息</span></div><div class="line">├── <span class="keyword">layout</span>        <span class="comment">//存放布局模板文件</span></div><div class="line">│   └── _partial  <span class="comment">//布局文件中可共用的模板</span></div><div class="line">└── <span class="keyword">source</span>        <span class="comment">//静态资源文件夹</span></div><div class="line">    ├── css</div><div class="line">    ├── fonts</div><div class="line">    ├── js</div><div class="line">    └── sass</div></pre></td></tr></table></figure>
<p>项目结构搞好就可以开始写代码了!因为当初我是仿<code>landscape</code>写的，而且<code>ejs</code>也是我之前看nodejs时就接触过的，因此就直接用ejs写模板文件了，样式使用了<code>sass (scss</code>。</p>
<h2 id="布局"><a href="#布局" class="headerlink" title="布局"></a>布局</h2><h4 id="编写布局文件-layout-ejs"><a href="#编写布局文件-layout-ejs" class="headerlink" title="编写布局文件(layout.ejs)"></a>编写布局文件(layout.ejs)</h4><p>模板文件在<code>layout</code>文件夹下，文件名对应Hexo中的模板名，有<code>index</code>,<code>post</code>,<code>page</code>,<code>archive</code>,<code>category</code>,<code>tag</code>几种，对于普通的<code>header + content + footer</code>的页面结构，<code>header</code>和<code>footer</code>往往是可以复用的，因此我们可以使用<code>layout.ejs</code>进行布局，动态的内容使用<code>body</code>变量去动态渲染，所以我的<code>layout.ejs</code>大概长这样:</p>
<figure class="highlight erb"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div></pre></td><td class="code"><pre><div class="line"><span class="xml"><span class="meta">&lt;!doctype html&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">html</span> <span class="attr">lang</span>=<span class="string">"en"</span>&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">charset</span>=<span class="string">"UTF-8"</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">meta</span> <span class="attr">name</span>=<span class="string">"viewport"</span> <span class="attr">content</span>=<span class="string">"width=device-width, initial-scale=1.0, user-scalable=no"</span>/&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">title</span>&gt;</span><span class="tag">&lt;<span class="name">%=</span></span></span><span class="ruby"> config.title </span><span class="xml"><span class="tag">%&gt;</span><span class="tag">&lt;/<span class="name">title</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> css(<span class="string">'css/style'</span>) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> partial(<span class="string">'_partial/header'</span>) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"main"</span>&gt;</span></span></div><div class="line"><span class="xml">        <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> body </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> partial(<span class="string">'_partial/footer'</span>) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> js(<span class="string">'js/index.js'</span>) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;/<span class="name">html</span>&gt;</span></span></div></pre></td></tr></table></figure>
<p><code>partial</code>,<code>js</code>和<code>css</code>是Hexo提供的辅助函数，后面再说。</p>
<h4 id="其他模板文件"><a href="#其他模板文件" class="headerlink" title="其他模板文件"></a>其他模板文件</h4><p>每一个模板文件对应的是一种布局，当你使用<code>hexo new &lt;title&gt;</code>的时候，其实忽略了一个参数，完整的命令是<code>hexo new [layout] &lt;title&gt;</code>，这个<code>layout</code>就决定了文章使用何种方式布局，比如创建一个自己简介的About页面，<code>hexo new page &quot;about&quot;</code>其实就是使用了page布局。每种布局对应到我们的模板文件上就是<code>index.ejs(首页)</code>,<code>post.ejs(文章)</code>,<code>archive.ejs(归档)</code>,<code>tag.ejs(标签归档)</code>,<code>page.ejs(分页)</code>。</p>
<p>如果更直观一点，url和模板的对应关系是这样的:</p>
<table>
<thead>
<tr>
<th>Url</th>
<th>Description</th>
<th>Layout</th>
</tr>
</thead>
<tbody>
<tr>
<td>/</td>
<td>首页</td>
<td>index.ejs</td>
</tr>
<tr>
<td>/yyyy/mm/dd/:title/</td>
<td>文章</td>
<td>post.ejs</td>
</tr>
<tr>
<td>/archives/</td>
<td>归档</td>
<td>archive.ejs</td>
</tr>
<tr>
<td>/tags/:tagname/</td>
<td>某个标签的归档</td>
<td>tag.ejs</td>
</tr>
<tr>
<td>/:else/</td>
<td>其他</td>
<td>page.ejs</td>
</tr>
</tbody>
</table>
<h4 id="index-ejs"><a href="#index-ejs" class="headerlink" title="index.ejs"></a>index.ejs</h4><p>首页一般是一些博文的摘要和一个分页器，通过Hexo的<code>page</code>变量拿到页面的数据渲染即可，这里我们不直接在<code>index.ejs</code>中写HTML结构，新建一个<code>_partial/article.ejs</code>，将文章数据传给子模板渲染，然后再额外传入一个参数<code>{index: true}</code>，对后面的<code>post.ejs</code>和<code>page.ejs</code>加以区分，让子模板能正确渲染。最后，index.ejs大致是这样的:</p>
<figure class="highlight mojolicious"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="xml">//index.ejs</span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">%</span></span></span><span class="perl"> page.posts.each(function(post, <span class="keyword">index</span>)&#123; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="perl">- partial(<span class="string">'_partial/article'</span>, &#123;<span class="keyword">index</span>: true, post: post&#125;) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">%</span></span></span><span class="perl"> &#125;) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"pagination"</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="perl">- paginator(&#123; total: Math.ceil(site.posts.length / config.per_page)&#125;) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></div></pre></td></tr></table></figure>
<h4 id="post-ejs"><a href="#post-ejs" class="headerlink" title="post.ejs"></a>post.ejs</h4><p>文章模板和首页差不多，只是对应的是一篇具体的文章，所以就把文章传入，再额外传入<code>{index: false}</code>告诉子模板不要按首页的方式去渲染就好了。就一行代码(因为都在子模板里 XD</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//post.ejs</span></div><div class="line">&lt;%- partial(<span class="string">'_partial/article'</span>, &#123;<span class="string">index:</span> <span class="literal">false</span>, <span class="string">post:</span> page&#125;) %&gt;</div></pre></td></tr></table></figure>
<h4 id="page-ejs"><a href="#page-ejs" class="headerlink" title="page.ejs"></a>page.ejs</h4><p>我个人对Page模板其实是有点懵逼的，在我自己的实践中是添加<code>about</code>(<code>hexo new page &quot;about&quot;</code>)页面后，访问<code>/about</code>会走分页布局，实际上这个页面对应的内容是<code>/source/about</code>里的<code>index.md</code>，也相当于对文章的渲染，因此我把Page模板也写成了和文章模板一样:</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//page.ejs</span></div><div class="line">&lt;%- partial(<span class="string">'_partial/article'</span>, &#123;<span class="string">index:</span> <span class="literal">false</span>, <span class="string">post:</span> page&#125;) %&gt;</div></pre></td></tr></table></figure>
<h4 id="partial-article-ejs"><a href="#partial-article-ejs" class="headerlink" title="_partial/article.ejs"></a>_partial/article.ejs</h4><p>前面一共有三处共用了article模板，另外page和post的一样的，所以实际上只有两种情况:主页(<code>index: true</code>)和非主页(<code>index: false</code>)。对应的<code>_partial/article.ejs</code>里只要判断这个值就可以正确渲染了，基本结构如下：</p>
<figure class="highlight gcode"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//_partial/article.ejs</span></div><div class="line">&lt;<span class="meta">%</span> <span class="keyword">if</span><span class="comment">(index)</span>&#123; <span class="meta">%</span>&gt;</div><div class="line">    <span class="comment">//index logic...</span></div><div class="line">&lt;<span class="meta">%</span> &#125;else&#123; <span class="meta">%</span>&gt;</div><div class="line">    <span class="comment">//post or page logic...</span></div><div class="line">&lt;<span class="meta">%</span> &#125; <span class="meta">%</span>&gt;</div></pre></td></tr></table></figure>
<h4 id="tag-ejs"><a href="#tag-ejs" class="headerlink" title="tag.ejs"></a>tag.ejs</h4><p><del>标签归档页内容很少，直接用Hexo的辅助函数<code>list_tags</code>生成一个标签的列表就ok了:</del><br>之前对tag模板的理解错误了，tag.ejs作用的是具体tag下的归档布局，因此和archive.ejs差不多:</p>
<figure class="highlight erb"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div></pre></td><td class="code"><pre><div class="line"><span class="xml">//tag.ejs</span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"tags"</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">h1</span>&gt;</span><span class="tag">&lt;<span class="name">%=</span></span></span><span class="ruby"> page.tag </span><span class="xml"><span class="tag">%&gt;</span><span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> page.posts.each(function(post)&#123; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">      <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"tag_item"</span>&gt;</span></span></div><div class="line"><span class="xml">        <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">"title"</span> <span class="attr">href</span>=<span class="string">"&lt;%-</span></span></span><span class="ruby"> url_for(post.path) </span><span class="xml"><span class="tag"><span class="string">%&gt;"</span>&gt;</span><span class="tag">&lt;<span class="name">%=</span></span></span><span class="ruby"> post.title </span><span class="xml"><span class="tag">%&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></div><div class="line"><span class="xml">        <span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">"date"</span>&gt;</span><span class="tag">&lt;<span class="name">%=</span></span></span><span class="ruby"> post.date.format(<span class="string">'YYYY-MM-DD'</span>) </span><span class="xml"><span class="tag">%&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></div><div class="line"><span class="xml">      <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> &#125;) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></div></pre></td></tr></table></figure>
<p>归档页模板和首页差不多，归档页只需要展示文章标题和最后的分页器就好:</p>
<figure class="highlight erb"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="xml">//archive.ejs</span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"archive"</span>&gt;</span></span></div><div class="line"><span class="xml">  <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> var lastyear; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">  <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> page.posts.each(function(post)&#123; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> var year = post.date.year() </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> <span class="keyword">if</span>(lastyear !== year)&#123; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">      <span class="tag">&lt;<span class="name">h4</span> <span class="attr">class</span>=<span class="string">"year"</span>&gt;</span><span class="tag">&lt;<span class="name">%=</span></span></span><span class="ruby"> year </span><span class="xml"><span class="tag">%&gt;</span><span class="tag">&lt;/<span class="name">h4</span>&gt;</span></span></div><div class="line"><span class="xml">      <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> lastyear = year </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> &#125; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"archive_item"</span>&gt;</span></span></div><div class="line"><span class="xml">      <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">"title"</span> <span class="attr">href</span>=<span class="string">"&lt;%-</span></span></span><span class="ruby"> url_for(post.path) </span><span class="xml"><span class="tag"><span class="string">%&gt;"</span>&gt;</span><span class="tag">&lt;<span class="name">%=</span></span></span><span class="ruby"> post.title </span><span class="xml"><span class="tag">%&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span></div><div class="line"><span class="xml">      <span class="tag">&lt;<span class="name">span</span> <span class="attr">class</span>=<span class="string">"date"</span>&gt;</span><span class="tag">&lt;<span class="name">%=</span></span></span><span class="ruby"> post.date.format(<span class="string">'YYYY-MM-DD'</span>) </span><span class="xml"><span class="tag">%&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></div><div class="line"><span class="xml">  <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> &#125;) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"pagination"</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> paginator(&#123; <span class="symbol">total:</span> Math.ceil(site.posts.length / config.per_page)&#125;) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></div></pre></td></tr></table></figure>
<p>至此，模板文件就写好了，对于<code>category</code>模板就放弃了，感觉比较鸡肋。。。</p>
<h2 id="变量"><a href="#变量" class="headerlink" title="变量"></a>变量</h2><p>其实在模板文件中我们已经看到了<code>page.post</code>,<code>site.posts.length</code>,<code>config.per_page</code>等等，页面的内容就是根据这些变量获取的，由Hexo提供，拿来直接用，Hexo提供了很多变量，但不是都很常用，一般就用到以下变量:</p>
<ul>
<li><code>site</code>: 对应整个网站的变量，一般会用到<code>site.posts.length</code>制作分页器</li>
<li><code>page</code>: 对应当前页面的信息，例如我在<code>index.ejs</code>中使用<code>page.posts</code>获取了当前页面的所有文章而不是使用<code>site.posts</code>。</li>
<li><code>config</code>: 博客的配置信息，博客根目录下的<code>_config.yml</code>。</li>
<li><code>theme</code>: 主题的配置信息，对于主题根目录下的<code>_config.yml</code>。</li>
</ul>
<h2 id="辅助函数-Helper"><a href="#辅助函数-Helper" class="headerlink" title="辅助函数(Helper)"></a>辅助函数(Helper)</h2><p>制作一个分页器，我们需要知道文章的总数和每页展示的文章数，然后通过循环生成每个link标签，还要根据当前页面判断link标签的active状态，但是在Hexo中这些都不用我们自己来做了!Hexo提供了<code>paginator</code>这一辅助函数帮助我们生成分页器，只需要将文章总数<code>site.posts.length</code>和每页文章数<code>config.per_page</code>传入就可以生成了。</p>
<h4 id="其他的Helper"><a href="#其他的Helper" class="headerlink" title="其他的Helper:"></a>其他的Helper:</h4><ul>
<li><code>list_tags([options])</code>: 快速生成标签列表</li>
<li><code>js(path/to/js)</code>, <code>css(path/to/css)</code> 用来载入静态资源，path可以是字符串或数组(载入多个资源)，默认会去<code>source</code>文件夹下去找。</li>
<li><code>partial(path/to/partial)</code> 引用字模板，默认会去<code>layout</code>文件夹下找。</li>
</ul>
<h2 id="样式"><a href="#样式" class="headerlink" title="样式"></a>样式</h2><p>知道了Hexo的渲染方式，我们就可以使用HTML标签+CSS样式个性化我们的主题了，推荐大家使用CSS预处理语言的一种来写样式，这样就可以通过预处理语言自身的特点让样式更灵活。</p>
<h2 id="其他"><a href="#其他" class="headerlink" title="其他"></a>其他</h2><h4 id="添加对多说和Disqus的支持"><a href="#添加对多说和Disqus的支持" class="headerlink" title="添加对多说和Disqus的支持"></a>添加对多说和Disqus的支持</h4><p>评论是很常用的功能，不如就直接在我们的主题里支持了，然后通过配置变量决定是否开启，评论区跟在文章内容下面，对于这种三方的代码块，最好也以<code>partial</code>的方式提取出来，方便移除或是替换。</p>
<figure class="highlight erb"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="xml">//_partial/article.ejs</span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">section</span> <span class="attr">class</span>=<span class="string">'post-content'</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> post.content </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;/<span class="name">section</span>&gt;</span></span></div><div class="line"><span class="xml">//评论部分，post.comments判断是否开启评论，config.duoshuo_shortname</span></div><div class="line"><span class="xml">和config.disqus_shortname来判断启用那种评论插件，这里优先判断了多说</span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> <span class="keyword">if</span>(post.comments)&#123; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">section</span> <span class="attr">id</span>=<span class="string">"comments"</span>&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> <span class="keyword">if</span> (config.duoshuo_shortname)&#123; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">            <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> partial(<span class="string">'_partial/duoshuo'</span>) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">        <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> &#125;<span class="keyword">else</span> <span class="keyword">if</span>(config.disqus_shortname)&#123; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">            <span class="tag">&lt;<span class="name">%-</span></span></span><span class="ruby"> partial(<span class="string">'_partial/disqus'</span>) </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">        <span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> &#125; </span><span class="xml"><span class="tag">%&gt;</span></span></div><div class="line"><span class="xml">    <span class="tag">&lt;/<span class="name">section</span>&gt;</span></span></div><div class="line"><span class="xml"><span class="tag">&lt;<span class="name">%</span></span></span><span class="ruby"> &#125; </span><span class="xml"><span class="tag">%&gt;</span></span></div></pre></td></tr></table></figure>
<p>再将多说和Disqus提供的js脚本代码放在<code>_partial/duoshuo.ejs</code>和<code>_partial/disqus.ejs</code>下就ok了~</p>
<h4 id="使用highlight-js提供代码高亮"><a href="#使用highlight-js提供代码高亮" class="headerlink" title="使用highlight.js提供代码高亮"></a>使用highlight.js提供代码高亮</h4><p>highlight.js提供了多种语言的支持和多种皮肤，用法也很简单，载入文件后调用初始化方法，一切都帮你搞定，对于使用那种皮肤，喜好因人而异，我们干脆在主题的配置文件中做成配置项让用户自己选择:</p>
<figure class="highlight clean"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//showonne/_config.yml</span></div><div class="line"></div><div class="line">...other configs</div><div class="line"></div><div class="line"># highlight.js</div><div class="line">highlight_theme: zenburn</div></pre></td></tr></table></figure>
<p>对应的<code>layout.ejs</code>中:</p>
<figure class="highlight routeros"><table><tr><td class="gutter"><pre><div class="line">1</div></pre></td><td class="code"><pre><div class="line">&lt;link <span class="attribute">rel</span>=<span class="string">"stylesheet"</span> <span class="attribute">href</span>=<span class="string">"//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/styles/&lt;%= theme.highlight_theme %&gt;.min.css"</span>&gt;</div></pre></td></tr></table></figure>
<p>样式文件通过CDN引入，因为不同皮肤对应不同的文件名，所以十分灵活。</p>
<h2 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h2><p>当初是对应着<code>landscape</code>照葫芦画瓢写的，最近回头来发现一些不合理的地方，所以就又改了改，也对应着写了这么一篇总结，接下来准备再把样式划分一下，对于颜色这类样式通过变量的方式提取出来，也变得可配置，能让主题更灵活一些。</p>
<h4 id="参考资源"><a href="#参考资源" class="headerlink" title="参考资源"></a>参考资源</h4><p><a href="https://hexo.io/zh-cn/api/helper.html" target="_blank" rel="external">了解辅助函数</a><br><a href="https://hexo.io/zh-cn/docs/templates.html" target="_blank" rel="external">模板</a><br><a href="https://hexo.io/zh-cn/docs/variables.html" target="_blank" rel="external">Hexo中的变量</a><br><a href="https://hexo.io/themes/" target="_blank" rel="external">Hexo主题列表</a><br><a href="http://dev.duoshuo.com/threads/541d3b2b40b5abcd2e4df0e9" target="_blank" rel="external">Hexo使用多说教程</a><br><a href="https://highlightjs.org/usage/" target="_blank" rel="external">How to use highlight.js</a></p>
</section>
    
      <div class="tags">
        <span>Tags:</span>
        
  <a href="/tags#hexo" >
    <span class="tag-code">hexo</span>
  </a>

  <a href="/tags#theme" >
    <span class="tag-code">theme</span>
  </a>

      </div>
    
    
<nav id="article-nav">
    
        <a href="/2017/08/30/介绍如何为-hexo-写一个本地的搜索引擎/" id="article-nav-newer" class="article-nav-link-wrap">
            <strong class="article-nav-caption">NEWER</strong>
            <div class="article-nav-title">
                
                    （转）介绍如何为 hexo 写一个本地的搜索引擎
                
            </div>
        </a>
    
    
        <a href="/2017/08/30/jQuery选择器总结/" id="article-nav-older" class="article-nav-link-wrap">
            <strong class="article-nav-caption">OLDER</strong>
            <div class="article-nav-title">jQuery选择器总结</div>
        </a>
    
</nav>


    <div class="money-like">
      <div class="reward-btn">
        赏
        <span class="money-code">
          <span class="wechat-code">
            <div class="code-image"></div>
            <b>使用微信打赏</b>
          </span>
        </span>
      </div>
      <p class="notice">若你觉得我的文章对你有帮助，欢迎点击上方按钮对我打赏</p>
    </div>
    <div class="qrcode">
      <canvas id="share-qrcode"></canvas>
 
      <p class="notice">扫描二维码，分享此文章</p>
    </div>
    
      <!-- UY BEGIN -->
      <div id="uyan_frame"></div>
      <script type="text/javascript" src="http://v2.uyan.cc/code/uyan.js?uid=2142069"></script>
      <!-- UY END -->
    
  </article>
</main>

<script>
  (function () {
    var url = 'https://ycg31.oschina.io/2017/08/30/写一个自己的HEXO主题/';
    var banner = ''
    if (banner) {
      $('#article-banner').css({
        'background-image': 'url(' + banner + ')'
      })
    } else {
      $('#article-banner').geopattern(url)
    }
    $('.header').removeClass('fixed-header')

     // error image
    $(".markdown-content img").on('error', function() {
      $(this).attr('src', 'http://file.muyutech.com/error-img.png') 
    })

    // zoom image
    $(".markdown-content img").on('click', function() {
      var src = $(this).attr('src')
      var imageW = $(this).width()
      var imageH = $(this).height()
      
      var zoom = ($(window).width() * 0.95 / imageW).toFixed(2)
      zoom = zoom < 1 ? 1 : zoom
      zoom = zoom > 2 ? 2 : zoom
      var transY = (($(window).height() - imageH) / 2).toFixed(2)

      $('body').append('<div class="image-view-wrap"><div class="image-view-inner"><img src="'+ src +'" /></div></div>')
      $('.image-view-wrap').addClass('wrap-active')
      $('.image-view-wrap img').css({
        'width': `${imageW}`,
        'transform': `translate3d(0, ${transY}px, 0) scale3d(${zoom}, ${zoom}, 1)`
      })
      $('html').css('overflow', 'hidden')

      $('.image-view-wrap').on('click', function() {
        $(this).remove()
        $('html').attr('style', '')
      })
    })

    // qrcode
    var qr = new QRious({
      element: document.getElementById('share-qrcode'),
      value: document.location.href
    });



    // gitment
    var gitmentConfig = "";
    if (gitmentConfig != "undefined") {
      var gitment = new Gitment({
        id: "（写一个自己的HEXO主题",
        owner: "",
        repo: "",
        oauth: {
          client_id: "",
          client_secret: ""
        },
        theme: {
          render(state, instance) {
            const container = document.createElement('div')
            container.lang = "en-US"
            container.className = 'gitment-container gitment-root-container'
            container.appendChild(instance.renderHeader(state, instance))
            container.appendChild(instance.renderEditor(state, instance))
            container.appendChild(instance.renderComments(state, instance))
            container.appendChild(instance.renderFooter(state, instance))
            return container;
          }
        }
      })
      gitment.render(document.getElementById('comments'))
    }
  })();
</script>

    <div class="scroll-top">
  <span class="arrow-icon"></span>
</div>
    <footer class="app-footer">
  <p class="copyright">
    &copy; 2017 | Proudly powered by <a href="https://hexo.io" target="_blank">Hexo</a>
    <br>
    Theme by <a href="https://github.com/yanm1ng">yanm1ng</a> | Mod by <a href="https://github.com/ycg31">ycg31</a>
  </p>
</footer>

<script>
  function async(u, c) {
    var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
    o.src = u;
    if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
    s.parentNode.insertBefore(o, s);
  }
</script>
<script>
  async("//cdn.bootcss.com/fastclick/1.0.6/fastclick.min.js", function(){
    FastClick.attach(document.body);
  })
</script>

<script>
  var hasLine = 'true';
  async("//cdn.bootcss.com/highlight.js/9.12.0/highlight.min.js", function(){
    $('figure pre').each(function(i, block) {
      var figure = $(this).parents('figure');
      if (hasLine == 'false') {
        figure.find('.gutter').hide();
      }
      var lang = figure.attr('class').split(' ')[1] || 'code';
      var codeHtml = $(this).html();
      var codeTag = document.createElement('code');
      codeTag.className = lang;
      codeTag.innerHTML = codeHtml;
      $(this).attr('class', '').empty().html(codeTag);
      figure.attr('data-lang', lang.toUpperCase());
      hljs.highlightBlock(block);
    });
  })
</script>
<!-- Baidu Tongji -->

<script src="/js/script.js"></script>
  </body>
</html>